package com.lance.answer.question_answer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.lance.answer.dto.XjCourseVideoInfo;
import com.lance.answer.dto.XjUserCourseInfo;
import com.lance.answer.gui.answer.AnswerObject;
import com.lance.answer.gui.answer.DealJsonString;
import com.lance.answer.gui.answer.Util;
import com.lance.answer.util.HttpUtil;
import com.lance.answer.util.XinJiangUtil;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.util.CollectionUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author fengx
 * 新疆一体化答题
 */
public class DoXJAnswerTmp {


    private static List<WebElement> findWeElements(WebDriver driver, String cssSelector, int second) {
        return (new WebDriverWait(driver, Duration.ofSeconds(second))).until((ExpectedCondition<List<WebElement>>)
                d -> {
                    assert d != null;
                    return d.findElements(By.cssSelector(cssSelector));
                });
    }


    public static void main(String[] args) throws IOException {

        int openCourseId = 33539;
        int sid = 0;  //FIXME 每个人的SID是会变的。
        String courseName = "2021春季 - 工商企业管理 - 开放";
        String subjectName = "个人与团队管理";

        InputStream inputStream = new FileInputStream("D:\\answers\\info\\" + subjectName + ".json");
        String videoInfoStr = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        XjCourseVideoInfo courseInfo = JSONObject.parseObject(videoInfoStr, XjCourseVideoInfo.class);

        InputStream inputStream2 = new FileInputStream("D:\\answers\\" + subjectName + ".json");
        String answerStr = IOUtils.toString(inputStream2, StandardCharsets.UTF_8);
        List<AnswerObject> list = JSONObject.parseArray(answerStr, AnswerObject.class);
        Map<String, AnswerObject> answerMap = Maps.newHashMap();
        for (AnswerObject answerObject : list) {
            answerMap.put(DealJsonString.delHTMLTag(Util.dealContent(answerObject.getQuestionTitle())), answerObject);
        }

        //   WebDriver driver = Util.getDriver("d:\\ynouAutoStudy\\chromedriver.exe");
        WebDriver driver = Util.getDriver("c:\\ynouAutoStudy\\chromedriver.exe");

        try {

            driver.get("https://xjskk.open.com.cn/stuspace-auth/#/login");
          //  XinJiangUtil.studentLogin(driver, "310103198404035028", "035028");
            XinJiangUtil.studentLogin(driver, "310114199608244810", "244810");
            Thread.sleep(2000);
            // FIXME 有的人报了多个专业
            for (WebElement we : findWeElements(driver, "div[class='part']", 20)) {
                System.err.println("we:"+we.getText());
                System.err.println("we1:"+we.getAttribute("title"));
                if (courseName.equals(we.getAttribute("title"))) {
                    we.click();
                    break;
                }
            }

            Thread.sleep(5000);
            Set<Cookie> cookies = driver.manage().getCookies();
            String studentSpaceProfile = Util.getStudentSpaceProfile2(cookies);
            String authorization = Util.getAuthorization2(cookies);
            Map<String, String> heads = Maps.newHashMap();
            String cookie = Util.getCookie(cookies);
            initHeads(heads, studentSpaceProfile, authorization);

            // 获取SID
            sid = getSid(openCourseId, cookie, heads);

            driver.get("https://xjskk.open.com.cn/stuspace/#/course?oId=" + openCourseId + "&sId=" + sid);
            for (XjCourseVideoInfo.ContentDTO content : courseInfo.getContent()) {
                boolean isGoOn = true;
                // 先看视频
                for (XjCourseVideoInfo.ContentDTO.ResourcesDTO resources : content.getResources()) {

                    //   final Semaphore lock = new Semaphore(1);
                    // 17：52
                    driver.navigate().refresh();
                    Thread.sleep(6000);
                    // 17：52

                    try {


                        boolean isFind = false;
                        while (!isFind){
                            //一、 保存视频信息
                            saveVideoInfo(openCourseId, resources, cookie, heads);
                            // FIXME 二、学完之后必须点击一下：
                            String watchVideoUrl = initWatchVideoString(openCourseId, sid, resources);
                            driver.get(watchVideoUrl);
                            Thread.sleep(8000);
                            driver.navigate().back();
                            Thread.sleep(5000);
                            // 如果没有考试得话就继续当前循环
                            if (content.getExamines().size() < 1) {
                                isGoOn = false;
                                break;
                            }
                            driver.navigate().refresh();
                            // 这里睡眠很关键，等待页面加载
                            Thread.sleep(6000);
                            // FIXME 开始做题
                            System.err.println("开始做题.....");
                            XjCourseVideoInfo.ContentDTO.ExaminesDTO examines = content.getExamines().get(0);
                            System.err.println("examines:" + examines);
                            // 异常说明答题次数达到了最大次数
                            // 1、点击答题
                            Thread.sleep(3000);
                            // FIXME 2021-10-27 增加试错机制，在这里判断是否可以点击当前页面的答题，如果在有答题的情况下不能正常答题就继续循环看视频
                            isFind =  clickAnswer(driver, examines);
                        }
                        if (!isGoOn) {
                            continue;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    // 正式开始答题
                    try {

                        Thread.sleep(3000);
                        // 2、确定答题
                        confirmAnswer(driver);
                        Thread.sleep(3000);
                        // 3、开始答题 TODO list-children-class children-div-top
                        List<WebElement> questionWeList = findWeElements(driver, "div[class^='list-children-class']", 20);
                        doAnswer(questionWeList, answerMap);
                        // 4、提交测验
                        Thread.sleep(2000);
                        btnClick(driver, "提交测验");
                        Thread.sleep(3000);
                        btnClick(driver, "确定");
                        Thread.sleep(2000);
                        // 答题完成后返回课程目录
                        btnClick(driver, "返回课程目录");

                    } catch (Exception e) {
                        e.printStackTrace();
                        System.err.println("continue");
                        continue;
                    }
                    Thread.sleep(2000);
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            driver.close();
            driver.quit();
        }
    }

    public static void btnClick(WebDriver driver, String btnName) {
        for (WebElement confirmBtn : driver.findElements(By.cssSelector("button[type='button']"))) {
            if (confirmBtn.getText().equals(btnName)) {
                confirmBtn.click();
                break;
            }
        }
    }

    public static void saveVideoInfo(int openCourseId, XjCourseVideoInfo.ContentDTO.ResourcesDTO resources,
                                     String cookie, Map<String, String> heads) throws Exception {
        String saveUrl = "https://xjskk.open.com.cn/api/student/student-space-service/resources/saveResourceTrace";
        JSONObject saveJson = initSaveJson(openCourseId, resources);
        String saveString = HttpUtil.postJson(saveUrl, saveJson, cookie, heads);

        int contentId = (int) JSON.parseObject(saveString).get("content");
        Thread.sleep(5 * 1000);
        // 更新观看时间
        String updateUrl = "https://xjskk.open.com.cn/api/student/student-space-service/resources/updateResourceTrace";
        JSONObject updateJson = initUpdateJson(openCourseId, contentId, resources);
        HttpUtil.postJson(updateUrl, updateJson, cookie, heads);
    }

    private static String initWatchVideoString(int openCourseId, int sid, XjCourseVideoInfo.ContentDTO.ResourcesDTO resources) {
        Map<String, Object> map = Maps.newLinkedHashMap();
        // FIXME
        map.put("sId", sid);
        map.put("oId", openCourseId);
        map.put("type", resources.getType());
        map.put("resourceId", resources.getResourceUid());
        map.put("link", resources.getFileId());
        map.put("extensionName",resources.getExtendName().substring(1));
        map.put("from", "menu");

        StringBuilder sb = new StringBuilder("https://xjskk.open.com.cn/stuspace/#/play?");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        String getUrl2 = sb.toString();
        getUrl2 = getUrl2.substring(0, getUrl2.length() - 1);
        return getUrl2;
    }

    private static void doAnswer(List<WebElement> questionWeList, Map<String, AnswerObject> answerMap) {
        for (WebElement questionWe : questionWeList) {
            WebElement titleWe = questionWe.findElement(By.className("children-value-class"));
            // fixme
            String title = titleWe.getText();
            title = Util.dealContent(title);
            title = DealJsonString.delHTMLTag(title);
            AnswerObject answerObject = answerMap.get(title);
            if (answerObject == null) {
                System.err.println("答案不存在:" + title);
                // FIXME 如果问题不存在，就用HANLP来匹配
                double similarity = 0.0;
                String answerTitle = "";
                for (Map.Entry<String, AnswerObject> entry : answerMap.entrySet()) {
                    double k1 = DealJsonString.getSimilarity(title, entry.getKey());
                    if (k1 > similarity) {
                        similarity = k1;
                        answerTitle = entry.getKey();
                    }
                }
                // 相似度为0.9 就选择
                if (similarity > 0.80) {
                    answerObject = answerMap.get(answerTitle);
                } else {
                    try {
                        System.err.println("==答案真的不存在===");
                        Thread.sleep(20000000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            System.err.println("answerObject:" + JSONObject.toJSONString(answerObject));
            assert answerObject != null;
            doChoiceExercise(questionWe, answerObject.getAnswers());
        }
    }

    private static void doChoiceExercise(WebElement answerElement, List<String> realAnswers) {
        // 遍历题目的每一个选项
        for (WebElement singleAnswerElement : answerElement.findElements(By.cssSelector("div[class='clearfix']"))) {
            String answerContent = singleAnswerElement.
                    findElement(By.cssSelector("span[class='option-value-class']")).getText();
            answerContent = Util.dealContent(answerContent);
            // 找到单选框或复选框
            // el-checkbox el-radio
            WebElement labelElement = singleAnswerElement.findElement(By.cssSelector("label[class^='el-']"));

            // 找到真正的点击按钮 el-radio__input el-checkbox__input
            WebElement realClickElement = singleAnswerElement.findElement(By.cssSelector("span[class^='el-']"));

            String labelClass = labelElement.getAttribute("class");

            // 单选或者判断题
            WebElement clickWebElement = null;
            if (labelClass.contains("radio")) {
                clickWebElement = labelElement.findElement(By.cssSelector("input[type='radio']"));
            }
            if (labelClass.contains("checkbox")) {
                clickWebElement = labelElement.findElement(By.cssSelector("input[type='checkbox']"));
            }
            // FIXME 判断题0：对 1：错
            // 这里的ID是每个选项的ID answerContent是每个选项的内容
            for (String realAnswer : realAnswers) {
                if (DealJsonString.delHTMLTag(answerContent).equals(DealJsonString.delHTMLTag(realAnswer))) {
                    assert clickWebElement != null;
                    if (!clickWebElement.isSelected()) {
                        realClickElement.click();
                    }
                }
            }


        }
    }

    public static int getSid(int openCourseId, String cookie, Map<String, String> heads) throws IOException {

        int sid = 0;
        String getCourseInfoUrl = "https://xjskk.open.com.cn/api/student/student-space-service/courses/" +
                "getStudentCourses?pageNumber=1&pageSize=2000000&status=1&courseNameCode=";
        XjUserCourseInfo userCourseInfo = JSON.parseObject(HttpUtil.get(getCourseInfoUrl, cookie, heads),
                XjUserCourseInfo.class);
        // 获取每个人每门课程独有的SID
        for (XjUserCourseInfo.ContentDTO.ItemsDTO items : userCourseInfo.getContent().getItems()) {
            if (openCourseId == items.getOpenCourseId()) {
                sid = items.getSelectCourseId();
                break;
            }
        }
        return sid;
    }


    public static void initHeads(Map<String, String> heads, String studentSpaceProfile, String authorization) {
        heads.put("referer", "https://xjskk.open.com.cn/stuspace/");
        heads.put("authority", "xjskk.open.com.cn");
        heads.put("path", "/api/student/student-space-service/resources/updateResourceTrace");
        heads.put("scheme", "scheme");
        heads.put("open-student-space-profile", studentSpaceProfile);
        heads.put("origin", "https://xjskk.open.com.cn");
        heads.put("authorization", authorization);
    }

    public static JSONObject initSaveJson(int openCourseId, XjCourseVideoInfo.ContentDTO.ResourcesDTO resources) {
        JSONObject saveJson = new JSONObject();
        // 课程ID，固定的
        saveJson.put("openCourseId", openCourseId);
        // 单个视频的资源ID
        saveJson.put("resourceUid", resources.getResourceUid());
        // 视频总时长
        saveJson.put("totalTime", resources.getTraceTime());
        saveJson.put("traceTime", 0);
        return saveJson;
    }

    public static JSONObject initUpdateJson(int openCourseId, int contentId, XjCourseVideoInfo.ContentDTO.ResourcesDTO resources) {
        JSONObject updateJson = new JSONObject();
        updateJson.put("openCourseId", openCourseId);
        updateJson.put("resourceUid", resources.getResourceUid());
        updateJson.put("traceTime", resources.getTraceTime());
        // 课程的ID
        updateJson.put("id", contentId);
        return updateJson;
    }

    public static boolean clickAnswer(WebDriver driver, XjCourseVideoInfo.ContentDTO.ExaminesDTO examines) {
        // fixme 按理说应该只选择最后一个答题
        boolean isFind = false;
        for (WebElement span : findWeElements(driver, "span[class='testName font-blue']", 30)) {
            if (DealJsonString.delHTMLTag(span.getText()).equals(DealJsonString.delHTMLTag(examines.getName()))) {
                // 点击完成之后要break
                span.click();
                isFind = true;
                break;
            }
        }
        return isFind ;
    }

    public static void confirmAnswer(WebDriver driver) {
        List<WebElement> saveButtons = findWeElements(driver, "button[type='button']", 30);
        if (!CollectionUtils.isEmpty(saveButtons)) {
            for (WebElement webElement : saveButtons) {
                String text = webElement.getText();
                if (text.contains("确 定")) {
                    webElement.click();
                    break;
                }
            }
        }
    }


}
